#import "BWCrossStitchStorage.h"

#import "BWThread.h"

#define INDEX_SCALE 100000
#define KEY(row,column)  (((row) * INDEX_SCALE) + column)


@implementation BWCrossStitchStorage

- (id) init
{
    if (self = [super init]) {
        symbols = [[NSMutableArray alloc] init];
        existanceSet = [[NSMutableIndexSet alloc] init];
    }

    return (self);

} // init


- (void) dealloc
{
    [symbols release];
    [existanceSet release];

    [super dealloc];

} // dealloc



- (BOOL) isSymbolAtRow: (int) row
                column: (int) column
{
    unsigned int key = KEY (row, column);
    
    BOOL ret = NO;
    if ([existanceSet containsIndex: key]) {
        ret = YES;
    }

    return (ret);

} // isSymbol


- (BOOL) getSymbol: (BWCrossStitch **) foundSymbol
             atRow: (int) row
            column: (int) column
{
    BOOL foundOne = NO;

    // if none found, foundSymbol becomes nil
    if (foundSymbol != NULL) {
        *foundSymbol = nil;
    }

    if ([self isSymbolAtRow: row  column: column]) {
        int i;
        int count = [symbols count];
        for (i = 0; i < count; i++) {
            BWCrossStitch *symbol = [symbols objectAtIndex: i];
            
            if ([symbol row] == row && [symbol column] == column) {
                if (foundSymbol != NULL) {
                    *foundSymbol = symbol;
                }
                foundOne = YES;
                break;
            }
        }
    }

    return (foundOne);

} // getSymbolAtRow



- (void) addStitchWithThread: (BWThread *) thread
             atRow: (int) row
            column: (int) column
               tag: (int) tag
{
    BWCrossStitch *symbol = [[BWCrossStitch alloc]
                                initWithRow: row
                                column: column
                                thread: thread
                                tag: tag];
    [self addStitch: symbol];
    [symbol release];

} // addStitchWithThread+tag


- (void) addStitchWithThread: (BWThread *) thread
                       atRow: (int) row
                      column: (int) column
{
    [self addStitchWithThread: thread
          atRow: row
          column: column
          tag: -1];

} // addStitchWithThread


- (void) addStitch: (BWCrossStitch *) stitch
{
    int row = [stitch row];
    int column = [stitch column];

    // there can be only one
    if ([self isSymbolAtRow: row  column: column]) {
        [self removeSymbolAtRow: row  column: column];
    }

    [symbols addObject: stitch];

    unsigned int key;
    key = KEY (row, column);
    [existanceSet addIndex: key];

} // addStitch


- (void) removeSymbolAtRow: (int) row
                    column: (int) column
{
    if ([self isSymbolAtRow: row  column: column]) {
        unsigned int key;
        key = KEY (row, column);
        [existanceSet removeIndex: key];
        
        NSEnumerator *enumerator = [symbols objectEnumerator];
        
        BWCrossStitch *symbol = nil;
        while (symbol = [enumerator nextObject]) {
            if ([symbol row] == row && [symbol column] == column) {
                break;
            }
        }

        if (symbol != nil) {
            [symbols removeObject: symbol];
        }
    }

} // removeSymbolAtRow


- (NSArray *) symbols
{
    return (symbols);
} // symbols


- (int) count
{
    return ([symbols count]);
} // count


- (BWCrossStitch *) symbolAtIndex: (int) index
{
    BWCrossStitch *symbol = [symbols objectAtIndex: index];

    return (symbol);

} // symbolAtIndex



- (void) purge
{
    [symbols release];
    symbols = [[NSMutableArray alloc] init];
    [existanceSet release];
    existanceSet = [[NSMutableIndexSet alloc] init];

} // purge


- (void) encodeWithCoder: (NSCoder *) coder
{
    [coder encodeObject: symbols];
    [coder encodeObject: existanceSet];

} // encodeWithCoder


- (id) initWithCoder: (NSCoder *) coder
{
    if (self = [super init]) {
        symbols = [[coder decodeObject] retain];

        id indexSet; // not mutable coming out of the coder. sigh.

        indexSet = [[coder decodeObject] retain];

        existanceSet = [indexSet mutableCopy];
    }

    return (self);

} // initWithCoder



@end // BWCrossStitchStorage


